// -----------------------------------------------------------------------
//  <copyright file="LoggingBehaviour.cs" company="LiuliuSoft">
//      Copyright (c) 2022-2024 DaprPlus. All rights reserved.
//  </copyright>
//  <site>https://dapr.plus</site>
//  <last-editor>郭明锋</last-editor>
//  <last-date>2024/12/5 20:18:30</last-date>
// -----------------------------------------------------------------------

using System.Diagnostics;

using DaprPlus.Properties;

using OSharp.Json;


namespace DaprPlus.MediatR.Behaviors;

public class LoggingBehavior<TRequest, TResponse>(ILogger<LoggingBehavior<TRequest, TResponse>> logger)
    : IPipelineBehavior<TRequest, TResponse>
    where TRequest : IRequest<TResponse>
{
    private readonly Stopwatch _watch = new();

    public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next,
        CancellationToken cancellationToken)
    {
        var isCommand = request is ICommand || request.GetType().Name.EndsWith("Command");
        var behavior = isCommand
            ? ResDaprPlus.String_MediatR_LoggingBehavior_Name_Command
            : ResDaprPlus.String_MediatR_LoggingBehavior_Name_Query;
        var correlationId = Guid.NewGuid().GetHashCode();
        var requestName = typeof(TRequest).Name;

        string? requestDesc;
        try
        {
            requestDesc = requestName.ToTextJson();
            if (requestDesc.Length > 100)
            {
                requestDesc = requestDesc[..100];
            }
        }
        catch
        {
            requestDesc = request.GetType().FullName;
        }
        logger.LogInformation(ResDaprPlus.Format_MediatR_LoggingBehavior_Handing, behavior, requestName, correlationId, requestDesc);
        try
        {
            _watch.Start();
            var response = await next();
            _watch.Stop();
            logger.LogInformation(ResDaprPlus.Format_MediatR_LoggingBehavior_Handed, behavior, requestName, correlationId,
                _watch.Elapsed.TotalMilliseconds, _watch.Elapsed);
            logger.LogDebug(ResDaprPlus.Format_MediatR_LoggingBehavior_Result, behavior, response);
            return response;
        }
        catch (Exception ex)
        {
            _watch.Stop();
            logger.LogError(ex, ResDaprPlus.Format_MediatR_LoggingBehavior_Error, behavior, requestName, correlationId,
                _watch.Elapsed.TotalMilliseconds, _watch.Elapsed);
            throw;
        }
    }
}
